package Template;

import com.intellij.ide.actions.ContextHelpAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFileManager;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by huzhipeng on 2016/12/6.
 */
public class MvpCreateAction extends ContextHelpAction {

    private Project project;
    //包名
    private String packageName = "";
    private String mAuthor = "";//作者
    private String className = "";//类的名字
    private String mModuleName = "app";//模块名称
    private String mPath = "";//设置的最后的路径
    private int mPosition = 1; //记录选择的位置
    private String endPath = "";    //最后的那个路径

    private enum  CodeType {
        Activity,
        Fragment,
        Contract,
        ActivityPresenter,
        FragmentPresenter,
        Module, Component,
        FragmentModule,
        FragmentComponent,
        FragmentList,
        FragmentListAdapter,
        FragmentListModule,
        FragmentListContract,
        FragmentListComponent,
        FragmentListPresenter
    }

    @Override
    public void actionPerformed(AnActionEvent e) {
        project = e.getData(PlatformDataKeys.PROJECT);
        packageName = getPackageName();
        init(e);
    }

    /**
     * 刷新项目
     * @param e
     */
    private void refreshProject(AnActionEvent e) {
        try {
            e.getProject().getBaseDir().refresh(false, true);
        } catch (Exception e1) {

        }
    }

    /**
     * 初始化Dialog
     */
    private void init(AnActionEvent e){
        MyDialog myDialog = new MyDialog(new MyDialog.DialogCallBack() {
            @Override
            public void ok(String author, String className, String path, String moduleName, int position) {
                if (!"".equals(moduleName)) {
                    mModuleName = moduleName;
                }
                mAuthor = author;
                MvpCreateAction.this.className = className;
                mPath = path;
                endPath = path;
                createClassFiles(position);
                Messages.showInfoMessage(project,"create mvp code success\nPlease ReBuild Project","提示");
                //刷新列表，
                VirtualFileManager.getInstance().asyncRefresh(null);
            }
        });
        myDialog.setVisible(true);
    }

    /**
     * 生成类文件
     */
    private void createClassFiles(int position) {
        this.mPosition = position;
        if (position == 1) {
            createClassFile(CodeType.Component);
            createClassFile(CodeType.Contract);
            createClassFile(CodeType.Module);
            createClassFile(CodeType.ActivityPresenter);
            createClassFile(CodeType.Activity);
        } else if (position == 2){
            createClassFile(CodeType.Component);
            createClassFile(CodeType.Contract);
            createClassFile(CodeType.Module);
            createClassFile(CodeType.FragmentPresenter);
            createClassFile(CodeType.Fragment);
        } else {
            createClassFile(CodeType.FragmentListComponent);
            createClassFile(CodeType.FragmentListContract);
            createClassFile(CodeType.FragmentListModule);
            createClassFile(CodeType.FragmentListPresenter);
            createClassFile(CodeType.FragmentList);
            createClassFile(CodeType.FragmentListAdapter);
        }
    }

    /**
     * 生成mvp框架代码
     * @param codeType
     */
    private void createClassFile(CodeType codeType) {
        String fileName = "";
        String content = "";
        String appPath = getAppPath() + "ui/activity/" + mPath;
        String adapterPath = getAppPath() + "ui/adapter/" + mPath;
        switch (codeType){
            case Activity:
                fileName = "TemplateActivity.txt";
                content = ReadTemplateFile(fileName);
                content = dealTemplateContent(content);
                writeToFile(content, appPath + "", className + "Activity.kt");
                break;
            case Fragment:
                fileName = "TemplateFragment.txt";
                content = ReadTemplateFile(fileName);
                content = dealTemplateContent(content);
                writeToFile(content, appPath + "", className + "Fragment.java");
                break;
            case Contract:
                fileName = "TemplateContract.txt";
                content = ReadTemplateFile(fileName);
                content = dealTemplateContent(content);
                writeToFile(content, appPath + "/contract", className + "Contract.kt");
                break;
            case ActivityPresenter:
                fileName = "TemplatePresenter.txt";
                content = ReadTemplateFile(fileName);
                content = dealTemplateContent(content);
                writeToFile(content, appPath + "/presenter", className + "Presenter.kt");
                break;
            case Module:
                fileName = "TemplateModule.txt";
                content = ReadTemplateFile(fileName);
                content = dealTemplateContent(content);
                writeToFile(content, appPath + "/module", className + "Module.kt");
                break;
            case Component:
                fileName = "TemplateComponent.txt";
                content = ReadTemplateFile(fileName);
                content = dealTemplateContent(content);
                writeToFile(content, appPath + "/component", className + "Component.kt");
                break;
            case FragmentModule:
                fileName = "TemplateFragmentModule.txt";
                content = ReadTemplateFile(fileName);
                content = dealTemplateContent(content);
                writeToFile(content, appPath + "/module", className + "Module.java");
                break;
            case FragmentComponent:
                fileName = "TemplateFragmentComponent.txt";
                content = ReadTemplateFile(fileName);
                content = dealTemplateContent(content);
                writeToFile(content, appPath + "/component", className + "Component.java");
                break;
            case FragmentPresenter:
                fileName = "TemplatePresenterFragment.txt";
                content = ReadTemplateFile(fileName);
                content = dealTemplateContent(content);
                writeToFile(content, appPath + "/presenter", className + "Presenter.java");
                break;
            //List形式
            case FragmentListComponent:
                fileName = "TemplateFragmentListComponent.txt";
                content = ReadTemplateFile(fileName);
                content = dealTemplateContent(content);
                writeToFile(content, appPath + "/component", className + "ListComponent.java");
                break;
            case FragmentListContract:
                fileName = "TemplateFragmentListContract.txt";
                content = ReadTemplateFile(fileName);
                content = dealTemplateContent(content);
                writeToFile(content, appPath + "/contract", className + "ListContract.java");
                break;
            case FragmentListModule:
                fileName = "TemplateFragmentListModule.txt";
                content = ReadTemplateFile(fileName);
                content = dealTemplateContent(content);
                writeToFile(content, appPath + "/module", className + "ListModule.java");
                break;
            case FragmentListPresenter:
                fileName = "TemplateFragmentListPresenter.txt";
                content = ReadTemplateFile(fileName);
                content = dealTemplateContent(content);
                writeToFile(content, appPath + "/presenter", className + "ListPresenter.java");
                break;
            case FragmentList:
                fileName = "TemplateFragmentList.txt";
                content = ReadTemplateFile(fileName);
                content = dealTemplateContent(content);
                writeToFile(content, appPath + "", className + "ListFragment.java");
                break;
            case FragmentListAdapter:
                fileName = "TemplateFragmentListAdapter.txt";
                content = ReadTemplateFile(fileName);
                content = dealTemplateContent(content);
                writeToFile(content, adapterPath + "", className + "ListAdapter.java");
                break;
        }
    }

    /**
     * 生成
     * @param content 类中的内容
     * @param classPath 类文件路径
     * @param className 类文件名称
     */
    private void writeToFile(String content, String classPath, String className) {
        try {
            File floder = new File(classPath);
            if (!floder.exists()){
                floder.mkdirs();
            }

            File file = new File(classPath + "/" + className);
            if (!file.exists()) {
                file.createNewFile();
            }
            FileWriter fw = new FileWriter(file.getAbsoluteFile());
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(content);
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 获取包名文件路径
     * @return
     */
    private String getAppPath(){
        String packagePath = packageName.replace(".", "/");
        String appPath = project.getBasePath() + "/" + mModuleName + "/src/main/java/" + packagePath + "/";
        return appPath;
    }

    /**
     * 替换模板中字符
     * @param content
     * @return
     */
    private String dealTemplateContent(String content) {
        content = content.replace("$name", className);
        if (content.contains("$packagename")){
            content = content.replace("$packagename", packageName + ".ui.activity." + mPath.toLowerCase());
        }
        if (content.contains("$basepackagename")){
            content = content.replace("$basepackagename", packageName + ".base");
        }
        content = content.replace("$author", mAuthor);
        content = content.replace("$endpath", endPath);
        content = content.replace("$minname", className.substring(0, 1).toLowerCase() + className.substring(1, className.length()));
        content = content.replace("$date", getDate());
        content = content.replace("$pack", packageName + "");
        if (mPosition == 1) {
            content = content.replace("$sort", "Activity");
        } else if (mPosition == 2){
            content = content.replace("$sort", "Fragment");
        } else {
            content = content.replace("$sort", "Fragment");
        }
        return content;
    }

    /**
     * 获取当前时间
     * @return
     */
    public String getDate() {
        Date currentTime = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        String dateString = formatter.format(currentTime);
        return dateString;
    }


    /**
     * 读取模板文件中的字符内容
     * @param fileName 模板文件名
     * @return
     */
    private String ReadTemplateFile(String fileName) {
        InputStream in = null;
        in = this.getClass().getResourceAsStream("/Template/" + fileName);
        String content = "";
        try {
            content = new String(readStream(in));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return content;
    }


    private byte[] readStream(InputStream inputStream) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = -1;
        try {
            while ((len = inputStream.read(buffer)) != -1){
                outputStream.write(buffer, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            outputStream.close();
            inputStream.close();
        }

        return outputStream.toByteArray();
    }

    /**
     * 从AndroidManifest.xml文件中获取当前app的包名
     * @return
     */
    private String getPackageName() {
        String package_name = "";
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

        try {
            DocumentBuilder db = dbf.newDocumentBuilder();

            Document doc = db.parse(project.getBasePath() + "/" + mModuleName + "/src/main/AndroidManifest.xml");

            NodeList nodeList = doc.getElementsByTagName("manifest");
            for (int i = 0; i < nodeList.getLength(); i++){
                Node node = nodeList.item(i);
                Element element = (Element) node;
                package_name = element.getAttribute("package");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return package_name;
    }
}
